#include "visit.h"

// node -> type = "compUnit"

void visit_compUnit(ASTNode* node, SymbolTable* s, BasicBlock* bb, Module* m) {
    // 遍历子节点
    if(!node) return;

    if(node -> children.size() == 0) return;

    // child 为类型(int float void)
    ASTNode* child = node->children[0];
    if(child->type == "constDecl"){

        // 在这里处理constDecl

        ASTNode* child_compunit = node->children[1];
        visit_compUnit(child_compunit, s, bb, m);

    }
    else if (child->type == "int" || child->type == "float") {
        // 处理变量声明

        // 检查 node->children[1] 是否存在
        if (node->children.size() < 2) {
            std::cerr << "缺少子节点，无法获取变量名" << std::endl;
            throw std::invalid_argument("缺少子节点，无法获取变量名");
        }

        // 获取变量名和值
        Ret_visit_argCompUnit* ret = visit_argCompUnit(node->children[1], s, m, bb);
        if(ret -> is_funcDef == false){
            string var_name = ret -> ident;
            variant<int, float, string> pre_data = ret -> init_val;
            variant<int, float> data;

            if(auto pval = std::get_if<string>(&pre_data)){
                Symbol* symbol_ident = s -> lookup(*pval);
                if(symbol_ident -> kind == VAR || symbol_ident -> kind == CONST){
                    if(symbol_ident -> type == "int"){
                        // LoadInst::create_load(m->get_int32_type(), symbol_ident->alloc, bb);
                        data = int(symbol_ident -> value);
                        
                    }
                    else if(symbol_ident -> type == "float"){
                        // LoadInst::create_load(m->get_float_ptr_type(), symbol_ident->alloc, bb);
                        data = float(symbol_ident -> value);
                        
                    }
                    else {
                        std::cerr << "visit_initVal :" << "不支持的类型: " << symbol_ident -> type << std::endl;
                        throw std::invalid_argument(string("visit_initVal :") + "不支持的类型: " + symbol_ident -> type);
                    }
                }
                else{
                    std::cerr << "visit_initVal :" << "不支持的类型: " << symbol_ident -> kind << std::endl;
                    throw std::invalid_argument(string("visit_initVal :") + "不支持的类型: " + to_string(symbol_ident -> kind));
                }
            }
            else if(auto pval = std::get_if<int>(&pre_data)){
                data = *pval;
                
            } 
            else if(auto pval = std::get_if<float>(&pre_data)){
                data = *pval;
                
            }
        
            
        

            std::string val_type = child->type;
            
            // 检查变量名是否重复
            if (s->lookup(var_name) != nullptr) {
                std::cerr << "变量名 " << var_name << " 重复命名" << std::endl;
                throw std::invalid_argument("变量名重复命名: " + var_name);
            }

            // 确保 variant 中只包含 int 或 float
            if (val_type == "int") {
                if (auto* p = std::get_if<int>(&data)) {
                    int value = *p;
                    Type* ir_type = m->get_int32_type();

                    // 创建常量
                    ConstantInt* ci = ConstantInt::get(value, m);
                    if (!ci) {
                        std::cerr << "无法创建 ConstantInt 对象" << std::endl;
                        throw std::runtime_error("ConstantInt 创建失败");
                    }

                    // 创建全局变量
                    GlobalVariable* gv = GlobalVariable::create(var_name, m, ir_type, false, ci);
                    if (!gv) {
                        std::cerr << "无法创建 GlobalVariable 对象" << std::endl;
                        throw std::runtime_error("GlobalVariable 创建失败");
                    }

                    // 添加符号到符号表
                    s->addSymbol(var_name, VAR, val_type, value, gv, nullptr, nullptr);
                } else {
                    std::cerr << "Expected int, but got float instead!" << std::endl;
                    throw std::invalid_argument("Expected int, but got float instead!");
                }
            }
            else if (val_type == "float") {
                if (auto* p = std::get_if<float>(&data)) {
                    float value = *p;
                    Type* ir_type = m->get_float_type();

                    // 创建常量
                    ConstantFP* fp_const = ConstantFP::get(value, m);
                    if (!fp_const) {
                        std::cerr << "无法创建 ConstantFP 对象" << std::endl;
                        throw std::runtime_error("ConstantFP 创建失败");
                    }

                    // 创建全局变量
                    GlobalVariable* gv = GlobalVariable::create(var_name, m, ir_type, false, fp_const);
                    if (!gv) {
                        std::cerr << "无法创建 GlobalVariable 对象" << std::endl;
                        throw std::runtime_error("GlobalVariable 创建失败");
                    }

                    // 添加符号到符号表
                    s->addSymbol(var_name, VAR, val_type, value, gv, nullptr, nullptr);
                } else {
                    std::cerr << "Expected float, but got int instead!" << std::endl;
                    throw std::invalid_argument("Expected float, but got int instead!");
                }
            }
            else {
                std::cerr << "不支持的类型: " << val_type << std::endl;
                throw std::invalid_argument("不支持的类型: " + val_type);
            }

            // 后续递归处理 compUnit
            ASTNode* child_argCompUnit = node->children[1];

            if (child_argCompUnit->children.size() >= 2) {
                ASTNode* child_compunit = child_argCompUnit->children[2];
                visit_compUnit(child_compunit, s, bb, m);
            }
            else {
                // 可选：打印警告信息
                std::cerr << "compUnit 子节点不足，跳过后续递归处理。" << std::endl;
            }
        }
        else if(ret -> is_funcDef == true){
            
            visit_funcDef(node->children[1]->children[1]->children[0], s, m, bb, ret->ident, child->type);
        }
    }
    else if(child->type == "void"){
        // 递归遍历子节点

        // 在这里处理void
        
        ASTNode* child_compunit = node->children[3];
        visit_compUnit(child_compunit, s, bb, m);
       
    }
    else if(child->type == "$"){
        return;
    }

}